Skip to content

Introduce opentelemetry in rewatch and setup new test infrastructure#8241

Open
nojaf wants to merge 16 commits intorescript-lang:masterfrom
nojaf:migrate-rewatch-tests
Open

Introduce opentelemetry in rewatch and setup new test infrastructure#8241
nojaf wants to merge 16 commits intorescript-lang:masterfrom
nojaf:migrate-rewatch-tests

Conversation

@nojaf
Copy link
Member

@nojaf nojaf commented Feb 5, 2026

This is a subset of #8231.

I wish to introduce open telemetry in Rewatch and migrate the bash tests to a new test suite.

The new tests would look like:

describe("build", () => {
  it("builds all packages from root", () =>
    runRewatchTest(async ({ cli }) => {
      await cli.build();
    }));
});

Where we capture all telemetry traces produced inside runRewatchTest and extract a deterministic snapshot of this:

// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`build > builds all packages from root 1`] = `
[
  "rewatch.build[working_dir=.]",
  "  initialize_build",
  "    packages.make",
  "      build.load_package_sources[package=@rewatch-test/app]",
  "      build.load_package_sources[package=@rewatch-test/library]",
  "      build.load_package_sources[package=rewatch-test-fixture]",
  "    packages.parse_packages",
  "    clean.cleanup_previous_build",
  "  incremental_build[module_count=3]",
  "    build.parse[dirty_modules=3]",
  "    build.compile",
  "      build.compile_wave[file_count=1]",
  "        build.compile_file[module=Library]",
  "      build.compile_wave[file_count=1]",
  "        build.compile_file[module=App]",
  "      build.compile_wave[file_count=1]",
  "        build.compile_file[module=Root]",
]
`;

With this telemetry we can easily update snapshots and assert all still works as expected.
By using Vitest we also have a proper test runner, so can run individual tests.
All tests also run in a sandbox folder in the /tmp, we they cannot interfere with each other.
And they can run in parallel.

The goal is too replace and remove the existing bash tests.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 6, 2026

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript-lang/rescript@8241

@rescript/darwin-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-arm64@8241

@rescript/darwin-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/darwin-x64@8241

@rescript/linux-arm64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-arm64@8241

@rescript/linux-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/linux-x64@8241

@rescript/runtime

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/runtime@8241

@rescript/win32-x64

npm i https://pkg.pr.new/rescript-lang/rescript/@rescript/win32-x64@8241

commit: bd3b38b

@nojaf nojaf force-pushed the migrate-rewatch-tests branch 2 times, most recently from 6fc10da to 0ce96cc Compare February 6, 2026 10:45
nojaf added 4 commits February 6, 2026 11:48
Add optional OTLP tracing export to rewatch, controlled by the
OTEL_EXPORTER_OTLP_ENDPOINT environment variable. When set, rewatch
exports spans via HTTP OTLP; when unset, tracing is a no-op.

Instrument key build system functions (initialize_build, incremental_build,
compile, parse, clean, format, packages) with tracing spans and attributes
such as module counts and package names.

Restructure main.rs to support telemetry lifecycle (init/flush/shutdown)
and fix show_progress to use >= LevelFilter::Info so -v/-vv don't
suppress progress messages. Also print 'Finished compilation' in
plain_output mode during watch full rebuilds.

Introduce a new Vitest-based test infrastructure in tests/rewatch_tests/
that replaces the bash integration tests. Tests spawn rewatch with an
OTLP endpoint pointing to an in-process HTTP receiver, collect spans,
and snapshot the resulting span tree for deterministic assertions.

Update CI, Makefile, and scripts/test.js to use the new test runner.
When stdin is a pipe (not a TTY), spawn a background thread that
monitors for EOF. This allows a parent process (such as the test
harness) to signal a graceful shutdown by closing stdin, without
relying on signals or lock file removal.
Add mtime and content-hash based deduplication to filter out phantom
and duplicate file system events. Normalize event kinds from atomic
writes (temp file + rename) so they are treated as content modifications
rather than create/remove cycles that trigger unnecessary full rebuilds.

This fixes issues on macOS (Create events from atomic writes), Linux
(duplicate inotify IN_MODIFY events), and Windows (Remove+Rename
sequences from atomic writes).
On Windows, bsc writes CRLF to stdout in text mode. When the original
source file uses LF line endings, the formatted output would introduce
unwanted CRLF conversions. Detect the original file's line ending style
and normalize the formatted output to match.
@nojaf nojaf force-pushed the migrate-rewatch-tests branch from 0ce96cc to 9ba38d7 Compare February 6, 2026 10:48
@nojaf
Copy link
Member Author

nojaf commented Feb 6, 2026

@rolandpeelen and @jfrolich this is already a good first carve out worth reviewing.

Changes to rewatch are minimal but I need some small fixes for the new test suite.
As I mentioned with passion: I want to get rid of the rewatch bash tests, so I will be fixing what I need in this PR. Will try do have a somewhat clean git history so it is easy to review.

Next steps would be to port more tests, but you can already take a look at the rewatch changes.

nojaf added 12 commits February 6, 2026 20:37
Propagate parent span through rayon in build.parse so build.parse_file
spans are properly nested under build.parse instead of appearing as
orphaned root spans.

Enrich build.compile_file span with package, suffix, module_system,
and namespace attributes for better observability.

Handle invalid config changes gracefully during watch mode: replace
.expect() with match to report the error and continue watching,
allowing the user to fix the config without restarting the watcher.
Add 7 new fixture packages to cover more configuration dimensions:
- commonjs: CommonJS module output with .bs.js suffix
- namespaced: namespace package with TestNS
- noop-ppx: lightweight cross-platform no-op PPX for testing
- with-deps: package depending on rescript-bun for clean tests
- with-dev-deps: multi-source dirs with dev dependencies
- with-jsx: JSX v4 with @rescript/react
- with-ppx: PPX integration using noop-ppx

Enhance test helpers:
- Normalize CRLF line endings in process output for Windows
- Support .bs.js artifacts in sandbox cleanup detection
- Add createCli, readFileInSandbox, writeFileInSandbox helpers
- Add OTEL config for build.parse_file and enriched compile_file spans
- Exclude noop-ppx from biome linting (CommonJS required)
Add tests for core build functionality:
- Build from a package subdirectory
- No stale artifacts on second build
- Filter flag to compile only matching modules

Add build error tests:
- Parse error reporting with file location
- Type error reporting
- Errors when a dependency module is deleted
- Circular dependency detection
Add module operation tests:
- File rename with and without dependents
- Duplicate module name detection
- Interface file compilation and error cases

Add namespace package tests:
- Build with namespace flag
- Namespace in compiler args
- File rename in namespaced package

Add dev-dependency tests:
- Dev source compiles with dev dependencies
- Non-dev source cannot use dev dependencies
- Clean removes dev source artifacts
Add build config tests:
- Experimental feature flags (valid, invalid key, invalid format)
- After-build hook execution (success and failure)
- Warning configuration in compiler args
- Warn-error CLI override
- Deprecated and unknown config field warnings

Add module system tests:
- CommonJS package with .bs.js suffix
- CommonJS in compiler args
- Suffix change triggers rebuild
- Duplicate package-spec suffix error

Add PPX integration tests using lightweight noop-ppx:
- PPX build produces output
- PPX flags in parser args
- PPX flags not in compiler args

Add JSX tests:
- JSX v4 build with @rescript/react
- JSX flags in parser args
- JSX preserve flag
Add tests for scoped clean, node_modules dependency cleanup,
and verifying no false compiler-update message after clean+rebuild.
Add format tests:
- Stdin formatting for .res and .resi
- Single file and all-files formatting
- Subdirectory-scoped formatting
- Check mode (pass and fail cases)

Add compiler-args tests:
- CWD invariance (same output from root and subdirectory)
- Warning flags in both parser and compiler args
Verify that a concurrent build is prevented while watch mode
holds the lock file.
Add watch mode tests:
- New file creation triggers compilation
- Warning persistence across incremental builds
- Config change triggers full rebuild
- Changes outside source dirs are ignored
- Missing source folder does not crash watcher
- Invalid config change recovery (watcher keeps running)
- File rename removes old artifacts and compiles new file
- File deletion removes artifacts
Tracing spans are thread-local, so compile_file spans created inside
Rayon's par_iter had no parent connection to the compile_wave span on
the main thread. Pass the wave span explicitly via `parent: &wave_span`
to establish the correct parent-child relationship.
@nojaf nojaf marked this pull request as ready for review February 6, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant